package common.web.servlet;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.zip.GZIPOutputStream;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import javax.servlet.http.HttpSession;

import common.serialization.IWebText;
import common.service.IService;
import common.service.ServiceFactory;
import common.web.WebHelper;

import util.ConfigUtil;
import util.StringUtil;

import net.sf.json.JSONObject;

public class BaseController extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws IOException, ServletException {
		try {
			execute(request, response);
		} catch (Exception e) {
			e.printStackTrace();
			throw new ServletException();
		}
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws IOException, ServletException {
		try {
			execute(request, response);
		} catch (Exception e) {
			e.printStackTrace();
			throw new ServletException();
		}
	}

	final public void execute(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		HttpSession session = request.getSession(true);

		String realPath = getServletContext().getRealPath("/");
		realPath = StringUtil.dealPath(realPath);
		if (ConfigUtil.getContextPath() == null) {
			ConfigUtil.setContextPath(request.getContextPath());// 设置上下文路径
			ConfigUtil.setRealPath(realPath);// 设置web路径
		}
		WebHelper webHelper = new WebHelper();
		webHelper.setRequest(request);
		webHelper.setSession(session);
		webHelper.setResponse(response);
		webHelper.setServletContext(getServletContext());
		webHelper.setContextPath(request.getContextPath());
		webHelper.setRealPath(realPath);

		/*
		JSONObject jsonObj = null;
		String jsonValue = request.getParameter("json");
		if (jsonValue != null) {
			jsonObj = JSONObject.fromObject(jsonValue);
		}*/
		try {
			String action = request.getParameter("action");
			String operate = request.getParameter("operate");
			
			Class<?> actionCl = Class.forName(action);
			Object actionObj = actionCl.newInstance();
			Object retObj = null;
			try {
				Method method = actionCl.getMethod(operate, WebHelper.class);
				retObj = method.invoke(actionObj, webHelper);
			} catch (Exception e) {
				e.printStackTrace();
				throw new Exception(e);
			}

			String characterEncoding = request.getCharacterEncoding();
			if (StringUtil.isNull(characterEncoding)) {
				characterEncoding = "UTF-8";
			}

			if (retObj != null && retObj instanceof IWebText) {
				ServletOutputStream out = null;

				String transferEncoding = getGZIPEncoding((HttpServletRequest) request);
				if (transferEncoding != null) {// 建立压缩流
					((HttpServletResponse) response).setHeader("Content-Encoding", transferEncoding);
					out = new GZIPEncodableResponse((HttpServletResponse) response).getOutputStream();
				} else {
					out = response.getOutputStream();
				}
				IWebText webText = (IWebText) retObj;
				String retStr = webText.outWebText();
				out.write(retStr.getBytes(characterEncoding));
				out.flush();
				out.close();
				out = null;
			} else if (retObj != null && retObj instanceof String) {
				String url = (String)retObj;
				try {
					request.getRequestDispatcher(url).forward(request, response);
				} catch (ServletException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			} else {

			}
		} catch (Exception ex) {
			response.setDateHeader("Expires", 0);
			response.setHeader("Cache-Control", "No-cache");
			ServletOutputStream out = response.getOutputStream();
			// response.setContentType("text/html;charset=utf-8");
			out.write(ex.getLocalizedMessage().getBytes(request.getCharacterEncoding()));
			out.flush();
			out.close();
			out = null;
			ex.printStackTrace();
			throw new Exception();
		} finally {
			
		}
	}

	/**
	 * 
	 * 简述：清除页面缓存
	 * 
	 * @param request
	 * @param response
	 */
	public static void setCache(HttpServletRequest request,
			HttpServletResponse response) {
		if (request.getProtocol().compareTo("HTTP/1.0") == 0) {
			response.setHeader("Pragma", "no-cache");
		}
		if (request.getProtocol().compareTo("HTTP/1.1") == 0) {
			response.setHeader("Cache-Control", "no-cache");
			// response.setHeader("Cache-Control", "max-age=10"); // 缓存10个文件
		}
		response.setDateHeader("Expires", 0);
	}

	private static String getGZIPEncoding(HttpServletRequest request) {
		String acceptEncoding = request.getHeader("Accept-Encoding");
		if (acceptEncoding == null)
			return null;
		acceptEncoding = acceptEncoding.toLowerCase();
		if (acceptEncoding.indexOf("x-gzip") >= 0) {
			return "x-gzip";
		}
		if (acceptEncoding.indexOf("gzip") >= 0) {
			return "gzip";
		}
		return null;
	}

	private class GZIPEncodableResponse extends HttpServletResponseWrapper {
		private GZIPServletStream wrappedOut;

		public GZIPEncodableResponse(HttpServletResponse response)
				throws IOException {
			super(response);
			wrappedOut = new GZIPServletStream(response.getOutputStream());
		}

		public ServletOutputStream getOutputStream() throws IOException {
			return wrappedOut;
		}

		private PrintWriter wrappedWriter;

		public PrintWriter getWriter() throws IOException {
			if (wrappedWriter == null) {
				wrappedWriter = new PrintWriter(new OutputStreamWriter(
						getOutputStream(), getCharacterEncoding()));
			}
			return wrappedWriter;
		}

		public void flush() throws IOException {
			if (wrappedWriter != null) {
				wrappedWriter.flush();
			}
			wrappedOut.finish();
		}
	}

	// ---------------gzip压缩流------------
	private class GZIPServletStream extends ServletOutputStream {
		private GZIPOutputStream outputStream;

		public GZIPServletStream(OutputStream source) throws IOException {
			outputStream = new GZIPOutputStream(source);
		}

		public void finish() throws IOException {
			outputStream.finish();
		}

		public void write(byte[] buf) throws IOException {
			outputStream.write(buf);
		}

		public void write(byte[] buf, int off, int len) throws IOException {
			outputStream.write(buf, off, len);
		}

		public void write(int c) throws IOException {
			outputStream.write(c);
		}

		public void flush() throws IOException {
			outputStream.flush();
		}

		public void close() throws IOException {
			outputStream.close();
		}
	}

}
